package manejadores;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import com.akcess.exception.Usuario_tiene_rolException;
import com.akcess.exception.UsuariosException;
import com.akcess.exception.UsuariosRecordCountException;
import com.akcess.vo.*;
import com.akcess.impl.*;
import com.akcess.dao.*;
import com.akcess.exception.RolException;
import java.sql.*;
import java.util.*;

/**
 *
 * @author Ramon
 */
public class ManejadorUsuarios {
private String mensajeProblema=null;
    private Connection conexion = null;

    public ManejadorUsuarios(Connection con) {
        this.conexion = con;
    }

    /**
     * Esta funcion cierra la conexion a la base de datos que se le es asignado al instanciar la clase.
     * @throws java.sql.SQLException
     */
    public void CerrarBD() throws SQLException {

        this.conexion.close();

    }
 /**
 * En esta funcion agrego un nuevo usuario y le asigno los roles. Con esta funcion 
  * se tocan dos tablas en la base de datos. La tabla usuarios y la tabla usuario_tiene_rol.
 * @param usuario Es el nuevo usuario que se desea agregar a la base de datos. El usuario ya debe tener dentro suyo los roles que se desea asignar.
 * @return Solo retorna 0 si todo anda bien.
 * @throws com.akcess.exception.Usuario_tiene_rolException
 * @throws java.lang.Exception
 */
    public boolean AgregarUsuario(Usuarios usuario) throws Usuario_tiene_rolException, UsuariosRecordCountException {
        try {
            UsuariosRecordCount RCUser;
            int CantRegistros = 0;
            int id_nuevoUser = 0;


            //Le asigno un id_usuario al nuevo usuario que llega
            UsuariosRecordCountDAOImpl RCDaoUser = new UsuariosRecordCountDAOImpl();
            RCUser = RCDaoUser.getRecordCount(this.conexion);
            CantRegistros = RCUser.getCount();
            id_nuevoUser = CantRegistros + 1;
            usuario.setId_usuario(id_nuevoUser);

            //Agrego a la base de datos el nuevo usuario y le asigno los roles.
            UsuariosDAOImpl manejadorUsuario = new UsuariosDAOImpl();
            manejadorUsuario.insert(usuario, this.conexion);
            Rol[] RolesUser = usuario.getRoles();
            for (int i = 0; i < RolesUser.length; i++) {
                this.AsignarRol(RolesUser[i], usuario);
            }


            return true;
        } catch (UsuariosException ex) {
            this.mensajeProblema=ex.getCausa();
            return false;
        }
    }
     /**
     * Recupera un String con un mensaje de la causa del problema al insertar una nueva reserva o al modificar una existente.
     * @return Un String que contiene el mensaje con la causa del problema y si NO hay problema retorna NULL
     */
    public String getMensajeProblem()
    {
        return this.mensajeProblema;
    }
/**
 * Retorna un vector con todos los usuarios que existen en la base de datos.
 * Estos usuarios no traen en su interior sus roles asignados.
 * @return Un vector de objetos de la clase usuarios. Son todos los usuarios del sistema, aunque esten o no borrados.
 * @throws com.akcess.exception.UsuariosException
 * @throws java.lang.Exception
 */
    public Usuarios[] listarUsuarios() throws UsuariosException, Exception {
        Usuarios[] listaUser = null;

        UsuariosDAOImpl manejadorUsuario = new UsuariosDAOImpl();
        listaUser = manejadorUsuario.findAll(this.conexion);
        return listaUser;

    }
/**
 * Borra un usuario del sistema de forma logica. Nunca de forma fisica. Para borrar de forma logica solo cambia la columna "Borrado" a true.
 * @param id_usuario Es el id del usuario que se desea borrar.
 * @param operador Es el id del operador que borro al usuario, luego esto se utiliza para el log.
 * @throws com.akcess.exception.UsuariosException
 * @throws java.lang.Exception
 */
    public void BorrarUsuarios(int id_usuario, int operador) throws UsuariosException, Exception {
        //No se borra nada en la base de datos, solo se pone al usuario como no visible.

        UsuariosPK userPK = new UsuariosPK(id_usuario);
        UsuariosDAOImpl userDAO = new UsuariosDAOImpl();
        Usuarios user = userDAO.findByPrimaryKey(id_usuario, this.conexion);
        user.setBorrado(true);
        user.setId_operador(operador);
        userDAO.update(userPK, user, this.conexion);
        Rol[] roles = user.getRoles();
        
        if (roles != null) {
            for (int i = 0; i < roles.length; i++) {
                this.DesasignarRol(roles[i], user);

            }
        }


    }
/**
 * La columna nombre operativo tiene valores unicos. Con esta funcion se trae un usuario determinado utilizando su nombre operativo.
 * @param nombreOp
 * @return Un objeto Usuarios que contiene todos los datos del usuario con ese nombre operativo. En los datos del usuario tampoco tienen los roles que el mismo tiene asignado.
 */
    public Usuarios traerUsuarioXnombreOp(String nombreOp) {
        try {
            // Esta parte va a cambiar si es que le ponemos al campo Nombre operativo como clave primaria
            // Aca ya no nos va a devolver un vector de "Usuarios".
            Usuarios[] vacoUnico;

            UsuariosDAOImpl manejadorUsuario = new UsuariosDAOImpl();
            vacoUnico = manejadorUsuario.findByNombreoperativo(nombreOp, this.conexion);

            if (vacoUnico.length != 0) {
                return vacoUnico[0];
            } else {
                return null;
            }

        } catch (UsuariosException ex) {
            return null;
        }
    }

/**
 * Asigna un rol determinado a un usuario espècifico. Agregando una fila en la tabla usuario_tiene_rol
 * @param rolsito Es un objeto Rol que indica el rol que le queremos asignar a un usuario especifo.
 * @param user Es un objeto Usuarios que indica el usuario que tendra el nuevo rol asignado.
 * @throws com.akcess.exception.Usuario_tiene_rolException
 */    
    public void AsignarRol(Rol rolsito, Usuarios user) throws Usuario_tiene_rolException {
        try {
            Usuario_tiene_rolDAOImpl ManagerUserRol = new Usuario_tiene_rolDAOImpl();
            Usuario_tiene_rol UserRol = ManagerUserRol.findByPrimaryKey((short) rolsito.getId_rol(), user.getId_usuario(), this.conexion);
            if (UserRol == null)//Supongo que esto tiene CERO, si es que no encuentra nada en la BD
            {
                UserRol = new Usuario_tiene_rol((short) rolsito.getId_rol(), user.getId_usuario());
                ManagerUserRol.insert(UserRol, this.conexion);
            }


        } catch (Usuario_tiene_rolException ex) {
            ex.printStackTrace();

        }

    }

    /**
     * Quita el rol indiacado a un usuario borrando una fila de la tabla rol_tiene_usuarios.
     * @param chauRol Es un objeto Rol que indica el rol que se desea sacar a un usuario.
     * @param user Es un obejto Usuarios que indica el usuario al cual se le desea desagsinar un rol.
     * @throws com.akcess.exception.Usuario_tiene_rolException
     */
    public void DesasignarRol(Rol chauRol, Usuarios user) throws Usuario_tiene_rolException {


        try {
            Usuario_tiene_rolPK UserRol = new Usuario_tiene_rolPK((short) chauRol.getId_rol(), user.getId_usuario());
            Usuario_tiene_rolDAOImpl ManagerUserRol = new Usuario_tiene_rolDAOImpl();
            ManagerUserRol.delete(UserRol, this.conexion);

        } catch (Usuario_tiene_rolException ex) {
            ex.printStackTrace();

        }

    }
/**
 * Traer un usuario de la base de datos.
 * @param idUser Es el id del usuario que se quiere traer de la base de datos.
 * @return Retorna un objeto del tipo Usuarios con todos los datos del usuario que tiene el idUser.
 * @throws com.akcess.exception.UsuariosException
 */
    public Usuarios ObtenerUsuario(int idUser) throws UsuariosException {
        Usuarios user = new Usuarios();
        try {
            UsuariosDAOImpl ManagerUser = new UsuariosDAOImpl();
            UsuariosPK userPK = new UsuariosPK();
            userPK.setId_usuario(idUser);
            user = ManagerUser.findByPrimaryKey(userPK, this.conexion);
        } catch (UsuariosException ex) {
            ex.printStackTrace();
        }
        return user;
    }
/**
 * Retorna los roles que tiene un determinado usuario.
 * @param idUser Es un entero que indica el id del usuario que queremos saber los roles.
 * @return Retorna un vector de objetos Rol, que indica los roles que tiene el usuario con el id especificado.
 * @throws com.akcess.exception.RolException
 */
    public Rol[] ObtenerRolDeUsuario(int idUser) throws RolException {
        RolDAOImpl rolDao = new RolDAOImpl();
        Rol[] roles = rolDao.BuscarRolesXusuario(idUser, this.conexion);
        return roles;
    }
/**
 * Modifica los roles que tiene asignado usuario determinado. Borrando todos los roles viejos y agregando los roles nuevos que es mandado por parametros. 
 * @param idUser Es un entero que indica el id del usuario que queremos modificar sus roles.
 * @param rolesModificados Es un vector de objetos roles, que contienen los nuevos roles que queremos asignar.
 * @throws com.akcess.exception.RolException
 * @throws com.akcess.exception.Usuario_tiene_rolException
 */
    public void ModificarRol(int idUser, Vector rolesModificados) throws RolException, Usuario_tiene_rolException {

        Rol[] rolesActuales = this.ObtenerRolDeUsuario(idUser);
        Usuario_tiene_rolPK duplaPK = new Usuario_tiene_rolPK();

        Usuario_tiene_rolDAOImpl manejaRelacion = new Usuario_tiene_rolDAOImpl();

        boolean band = false;
        int indice = 0;
        for (int i = 0; i < rolesActuales.length; i++) {
            for (int j = 0; j < rolesModificados.size(); j++) {
                Rol r1 = (Rol) rolesModificados.get(j);
                if (rolesActuales[i].getId_rol() == r1.getId_rol()) {
                    band = true;
                    indice = j;
                    break;
                }
            }
            if (band) {
                //borrar de vector atributos que Subtipo ya tiene loo asignado.
                rolesModificados.remove(indice);
                band = false;
            } else {
                //borrar de la base de datos los atributos que ya NO tengo.
                duplaPK.setId_rol((short) rolesActuales[i].getId_rol());
                duplaPK.setId_usuario(idUser);
                manejaRelacion.delete(duplaPK, this.conexion);
            }
        }
        //Agregamos los nuevos atributos, esos solamente quedaran en el vector....
        for (int i = 0; i < rolesModificados.size(); i++) {
            Rol auxRol = (Rol) rolesModificados.get(i);
            Usuario_tiene_rol relacion = new Usuario_tiene_rol();
            relacion.setId_rol((short) auxRol.getId_rol());
            relacion.setId_usuario(idUser);
            manejaRelacion.insert(relacion, this.conexion);
        }


    }
/**
 * Modifica los datos de un usuario determinado en la base de datos.  
 * @param idUser Es un entero que indica el id del usuario que queremos modificar sus datos en la base de datos.
 * @param user Es un objeto Usuarios que contiene los datos modificados del usuario con el id especificado.
 * @param hacer Es un booleano que indica si la contraseña del usuario debe o no ser reseteada.
 * @throws com.akcess.exception.UsuariosException 
 */
    public void ModificarUsuario(int idUser, Usuarios user, boolean hacer) throws UsuariosException {
        try {
            UsuariosDAOImpl ManagerUser = new UsuariosDAOImpl();
            UsuariosPK userPK = new UsuariosPK();
            userPK.setId_usuario(idUser);
            Usuarios usuario = ManagerUser.findByPrimaryKey(userPK, this.conexion);
            //Lo siguiente se agrega a User de modo a realizar el Update.
            user.setBorrado(usuario.getBorrado());
            //Para saber si viene de perfil(true) o de ModificarUsuario(false)
            if(!hacer){
                user.setContrasena(usuario.getContrasena());
            }
            user.setId_usuario(usuario.getId_usuario());
            user.setIdtipodoc(usuario.getIdtipodoc());
            ManagerUser.update(userPK, user, this.conexion);
        } catch (UsuariosException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Dado un usuario retorna un vector que contiene el id y nombre de cada modulo existente relacionado con el rol y tambien contiene
     * el id y nombre de los permisos u operaciones que se pueden realizar en dichos modulos.
     * @param con Representa la conexion existente a la BD, de modo a ingresar y obtener los datos requeridos.
     * @return El retorno es un vector de tipo NombresModulosOperaciones, conteniendo toda la informacion descrita anteriormente.
     * @throws com.akcess.exception.RolException Lanza excepciones del tipo RolException, creada por el DAOGenerator.
     */
    public NombresModulosOperaciones[] BuscarPermisosDeUser(Usuarios user) throws RolException {
        NombresModulosOperaciones[] vecPermisos = null;
        RolDAOImpl manejarRol = new RolDAOImpl();
        vecPermisos = manejarRol.BuscarOperacionesXuser(user.getId_usuario(), this.conexion);
        return vecPermisos;
    }
    /**
     * Este metodo reseteara una contraseña del usuario definido por idUser. Pondra la contraseña por default que es "usuario".
     * @param idOper Indica el id del operador que realiza la operacion de reseteo de contraseña.
     * @param idUser Indica el usuario cuya contraseña sera reseteada.
     * @throws com.akcess.exception.UsuariosException Lanza excepciones del tipo RolException, creada por el DAOGenerator.
     */
    public void ResetPassword(int idOper, int idUser) throws UsuariosException {
        try {
            //Primeros obtenemos de la BD el usuario al cual se le reseteara su contraseña.
            UsuariosDAOImpl ManagerUser = new UsuariosDAOImpl();
            UsuariosPK userPK = new UsuariosPK();
            userPK.setId_usuario(idUser);
            Usuarios usuario = ManagerUser.findByPrimaryKey(userPK, this.conexion);
            
            //Se cambia la contraseña del usuario por "usuario".
            usuario.setContrasena("usuario");
            
            ManagerUser.update(userPK, usuario, this.conexion);
            
        } catch (UsuariosException ex) {
            ex.printStackTrace();
        }
    }
    
    /**
     * Con esta funcion consultamos en la base de datos si el nombre operativo de un usuario 
     * esta disponible para su utilizacion. O sea verificamos si ese nombre ya existe en la BD.
     * @param nombreOperativo Es el nombre que buscaremos en la base de datos.
     * @return Retorna TRUE si es que esta disponible, y FALSE si no esta disponible ese nombre.
     * @throws com.akcess.exception.UsuariosException
     */
    public boolean NombreOperativoDisponible(String nombreOperativo) throws UsuariosException {
        
            UsuariosDAOImpl ManagerUser = new UsuariosDAOImpl();
            Usuarios [] vecUser=ManagerUser.findByNombreoperativo(nombreOperativo, this.conexion);
            if(vecUser.length!=0)
                return false;
            else
                return true;
    }
    
}
